/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.camelspit.preludetoarmageddon.handlers;
import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
/**
 *
 * @author DMK
 */
public class Server extends JFrame {

    protected LogonState state;
    protected int errors; // how many times an invalid password has been entered
    protected String name;
    protected String password;
    private JTextField enterField;
    private JTextArea displayArea;
    protected Socket connection;
    private ServerSocket server;
    protected ObjectOutputStream output;
    protected ObjectInputStream input;
    private int counter = 1;

    public Server() throws IOException {
        super("Game Server");
        enterField = new JTextField();
        enterField.setEditable(false);
        enterField.addActionListener(
                new ActionListener()
            {
                //send message to client
                public void actionPerformed(ActionEvent event) {
                    sendData(event.getActionCommand());
                    enterField.setText("");

                }
            });

        add(enterField, BorderLayout.SOUTH);

        displayArea = new JTextArea();
        add(new JScrollPane(displayArea), BorderLayout.CENTER);

        setSize(600, 400);
        setVisible(true);
    }

    //set up and run server
    public void runServer() {
        try {
            server = new ServerSocket(12345, 100);

            while(true) {
                try {
                    waitForConnection();
                    getStreams();
                    enter();
                    processConnection();
                }
                catch(EOFException eoex) {
                    displayMessage("\nServer terminated connection");
                }
                finally {
                    closeConnection();
                    counter++;
                }
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }

    //wait for connection to arrive
    private void waitForConnection() throws IOException {
        displayMessage("Waiting for connection.\n");
        connection = server.accept();
        displayMessage("Connection " + counter + "recieved from:" +
                connection.getInetAddress().getHostName());

    }

    //get streams to send and recieve data
    private void getStreams() throws IOException {
        output = new ObjectOutputStream(connection.getOutputStream());
        output.flush();

        input = new ObjectInputStream(connection.getInputStream());

        displayMessage("\nGot I/O streams.\n");
    }

    //process connection with client
    private void processConnection() throws IOException{
        String message = "Connection Successful";
        sendData(message);

        //enable enterfield so server can send messages
        setTextFieldEditable(true);

        do {
            try {
                message = (String)input.readObject();
                displayMessage("\n" + message);
            } catch(ClassNotFoundException cnfe) {
                displayMessage("\nUnknown object type recieved.");
            }
        } while(!message.equals("CLIENT>>> TERMINATE"));
    }

    //close streams and socket
    private void closeConnection() {
        displayMessage("\nTerminating connection.");
        setTextFieldEditable(false);

        try {
            output.close();
            input.close();
            connection.close();
        } catch(IOException ioe) {
            ioe.printStackTrace();
        }
    }

    //send message to client
    private void sendData(String message) {
        try {
            output.writeObject("SERVER>>> " + message);
            output.flush(); //flush output to client
            displayMessage("\nSERVER>>> " + message);
        } catch (IOException ioe) {
            displayArea.append("\nError writing object.");
        }
    }

    //manipulates display area in the event dispatching thread
    private void displayMessage(final String messageToDisplay) {
        SwingUtilities.invokeLater(
                new Runnable()
            {
                public void run() //updates displayArea
                {
                    displayArea.append(messageToDisplay);
                }
            }//end anonymous *inner class*
        );
    }

    //manipulates enterField in the event dispatch thread
    private void setTextFieldEditable(final boolean editable) {
        SwingUtilities.invokeLater(
                new Runnable() {
            public void run() {
                enterField.setEditable(editable);
            }
        });
    }



    public void enter()  {
        String welcomeMessage = "Welcome to Illuminati: Prelude to Armageddon\n"
                + "Please enter your name, or \"new\" if new user: ";
        sendData(welcomeMessage);
    }

    public void leave() {

    }

    public void hungup() {
        //add log message
    }

    public void flooded() {
        //add log message
    }

    public static void noRoom(Socket connection) throws IOException {
        final String msg = "Sorry, there is no more room on this server.\n";
        ObjectOutputStream output = new ObjectOutputStream(
                connection.getOutputStream());
        output.writeObject("SERVER>>> " + msg);

    }

    public void handle(String data) throws IOException {
        if(errors == 5) {
            sendData("Too many incorrect responses, closing connection...");
            input.close();
            output.close();
            connection.close();
            return;
        }
        if(state == LogonState.NEWCONNECTION) {
            if(data.equalsIgnoreCase("new")) {
                state = LogonState.NEWUSER;
                sendData("Please enter your desired name: ");
            }
            else {
                //
            }
        }
    }

    public void goToGame(boolean newbie) {

    }

    public static boolean acceptableName(String name) {

        return true;
    }

}
